import { MouseMacro, MacroAction } from "@/src/types/types";
import { eventCode2Keycode } from "./keycode";
import { shiftFrom16Bit, shiftTo16Bit } from "@/src/devices/WebHidAPI";
import keyInfoJson from "@/src/config/keyinfos.json";

// export type MacroAction = {
//     name: string,   //显示名称
//     code: number,   //按键值
//     type: number,   // 1 鼠标， 2 键盘
//     action: number, // 1 按下 2 松开
//     time?: number,
//     delay?: number  //延时
// }

// export type Macro = {
//     name: string,
//     list: MacroAction[]
// }

const codeMouseName = ['Mouse L-Button', 'Mouse M-Button', 'Mouse R-Button', 'Mouse Backward', 'Mouse Forward'];

const getName = (code: number, type: number) => {

    if (type == 1) {
        return codeMouseName[code];
    } else {
       const key =  keyInfoJson.keyInfos.find((keyInfo) => keyInfo.code1 == code)
       return key?.name || code +'';
    }
}

export const parseMacro = (macroData: number[], macroArr: MouseMacro[]) => {
    let newMacroArr: MouseMacro[] = macroArr.map((macro, index) => {
        
        if (macroData[index*2] == 0xff && macroData[index*2+1] == 0xff) {
            return macro;
        }
        if (macroData[index*2] == 0x0) {
            return macro;
        }

        let offset = shiftTo16Bit([macroData[index*2], macroData[index*2+1]]);

        if (offset > 4096) {
            return macro;
        }
        
        let end = false
        let list = [];
        do {
           const delay = shiftTo16Bit([macroData[offset], macroData[offset +1]]);
           console.log(macroData[offset+2]);
           let type = 0x01; // 鼠标
           if ((macroData[offset+2] & 0b111111) == 2) {
               type = 0x02;
           } else if ((macroData[offset+2] & 0b111111) == 4) {
               type = 0x03; // 滚轮
           }
           // const type = macroData[ offset+2] >> 1 & 0x1 ? 2 : 1;
           const action = macroData[offset+2] >> 6 & 0x1 ? 1 : 2;
           const code =  macroData[offset+3];
           list.push({
                name: getName(code, type),
                code,
                type,
                action,
                delay
           })
           end = (macroData[ offset+2] >> 7 & 0x1 ? true : false) || macroData[ offset+2] == 0;
           offset += 4;
        }
        while(!end)
        
        return {
            ...macro,
            list
        };
    });
    
    return newMacroArr;
}

export const getMacroBytes = (macroArr: MouseMacro[]) => {
    const macroBytes = Array(64).fill(0x00).concat(Array(4032).fill(0));
    let macroOffset = 64;
    
    macroArr.map((item: MouseMacro, index: number) => {
        if (item.list.length == 0) {
            return ;
        }
        const [lo, hi] = shiftFrom16Bit(macroOffset);
        macroBytes[index*2] = lo;
        macroBytes[index*2+1] = hi;

        item.list.map((actionItem: MacroAction, itemIndex: number) => {
            let action = 0;
            if (actionItem.action == 1) {
                action |= 1 << 6;
            }
            if (actionItem.type == 1) {
                action |= 3;
            }
            if (actionItem.type == 2) {
                action |= 1 << 1;
            }
            if (actionItem.type == 3) {
                action |= 4;
            }

            if (itemIndex == item.list.length - 1) {
                action |= 1 << 7
            }
            
            const [lo, hi] = shiftFrom16Bit(actionItem.delay || 0);

            macroBytes[macroOffset  + itemIndex*4 ] = lo;
            macroBytes[macroOffset  + itemIndex*4 + 1] = hi;
            macroBytes[macroOffset  + itemIndex*4 + 2] = action;
            macroBytes[macroOffset  + itemIndex*4 + 3] = actionItem.code;
        });

        macroOffset += item.list.length*4;

    })
    return macroBytes;
}

export const addMacroActionList = (actionList: MacroAction[], event: MouseEvent | KeyboardEvent, time: number, delayTime: number) => {
    const action = evtToAction(event);
    if (actionList.length > 0) {
        const lastAction = actionList.at(-1);
        if (lastAction !== undefined) {
            const newActionList = actionList.slice(0, -1);
            const actions = [{
                ...lastAction, delay: delayTime >= 0 ? delayTime : time - (lastAction.time || 0)
            }, {...action, time, delay: 0}]
            if (newActionList.length > 0) {
                return [...newActionList, ...actions];
            } else {
                return actions;
            }
        } else {
            return [];
        }
    } else {
        return [{...action, time, delay: 0}];
    }
}

export const evtToAction = (event: MouseEvent | KeyboardEvent) => {
    if (event instanceof MouseEvent) {
        const mouseButtons = ['Mouse L-Button', 'Mouse M-Button', 'Mouse R-Button', 'Mouse Backward', 'Mouse Forward'];
        const name = mouseButtons[event.button] || event.button+'';
        const code = event.button;
        const type = 1;
        const action = event.type == 'mousedown' ? 1 : 2;
        return {name, code, type, action};
    } else {
        const name = event.key.toUpperCase();
        const code = eventCode2Keycode(event.code);
        const type = 2;
        const action = event.type == 'keydown' ? 1: 2;
        return {name, code, type, action};
    }
}